package ua.com.stormlabs.tiny.licenseserver.controllers;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import ua.com.stormlabs.tiny.licenseserver.beans.License;
import ua.com.stormlabs.tiny.licenseserver.beans.Pager;
import ua.com.stormlabs.tiny.licenseserver.beans.User;
import ua.com.stormlabs.tiny.licenseserver.service.LicensesService;
import ua.com.stormlabs.tiny.licenseserver.service.UsersService;
import ua.com.stormlabs.tiny.licenseserver.storage.DuplicateLicenseException;
import ua.com.stormlabs.tiny.licenseserver.storage.LicenseNotFoundException;
import ua.com.stormlabs.tiny.licenseserver.storage.RequestResult;
import ua.com.stormlabs.tiny.licenseserver.storage.UserNotFoundException;
import ua.com.stormlabs.tiny.licenseserver.utils.ArgumentGuard;

import javax.validation.Valid;
import java.util.List;

/**
 * @author Maxim Bondarenko
 * @version 1.0 10/29/11
 */

@Controller
public class LicensesController {

    private static final Logger log = LoggerFactory.getLogger(LicensesController.class);

    private static final int PAGE_SIZE = 2;

    @Autowired
    private LicensesService licensesService;

    @Autowired
    private UsersService usersService;

    @Secured({"ROLE_ADMIN", "ROLE_STAFF"})
    @RequestMapping(value = "licenses/view", method = RequestMethod.GET)
    public String view(Model model, @RequestParam(defaultValue = "0") int pageNumber) {
        log.info("Getting all licenses...");

        RequestResult<License> licenses = licensesService.listLicenses(pageNumber, PAGE_SIZE);
        log.info("Found " + licenses.getTotalCount() + " licenses");
        model.addAttribute("licenses", licenses.getResult());
        model.addAttribute("pager", new Pager(pageNumber, licenses.getTotalCount(), PAGE_SIZE));
        return "licenses/view";
    }

    @Secured("ROLE_ADMIN")
    @RequestMapping(value = "licenses/add", method = RequestMethod.GET)
    public String addLicense(Model model) {
        log.info("Adding new license");

        License license = new License();
        license.setId(-1);
        license.setLicenseName("License Name");

        model.addAttribute("license", license);

        return "licenses/edit";
    }

    @Secured("ROLE_ADMIN")
    @RequestMapping(value = "licenses/add", method = RequestMethod.POST)
    public String insert(@Valid License license, Model model) {
        log.info("Inserting license: " + license);
        try {
            licensesService.createLicense(license.getLicenseName());
        } catch (DuplicateLicenseException e) {
            log.warn("Duplicate name");
            model.addAttribute("license", license);
            model.addAttribute("error", "name");
            return "licenses/edit";
        }
        log.info("Event inserted: " + license);
        return "redirect:/licenses/view";
    }

    @Secured("ROLE_ADMIN")
    @RequestMapping(value = "licenses/deleteLicense", method = RequestMethod.GET)
    public String deleteLicense(@RequestParam int id,
                                @RequestParam(defaultValue = "1") int pageNumber, Model model) {
        log.info("Deleting license with id: " + id);

        List<User> users = usersService.listUsers(id);
        if (!users.isEmpty()) {
            log.debug("License with id " + id + " have active users, unable to delete");
            model.addAttribute("deleteError", true);
            return "redirect:/licenses/view?pageNumber=" + pageNumber;
        }

        try {
            licensesService.deleteLicenseById(id);
        } catch (LicenseNotFoundException e) {
            log.error("Exception: " + e, e);
        }

        return "redirect:/licenses/view?pageNumber=" + pageNumber;
    }

    @Secured("ROLE_ADMIN")
    @RequestMapping(value = "licenses/isUnique", method = RequestMethod.GET)
    @ResponseBody
    public Boolean isLicenseNameUnique(@RequestParam String licenseName, @RequestParam int licenseId)
            throws UserNotFoundException, LicenseNotFoundException {
        ArgumentGuard.checkNotNull(licenseName, "licenseName");
        ArgumentGuard.checkNotBlank(licenseName, "licenseName");

        log.debug("Checking license name: [" + licenseName + "], user id: [" + licenseId + "]");

        if (licenseId == -1) {
            try {
                licensesService.getLicenseByName(licenseName);
                log.debug("License with name [" + licenseName + "] already exists");
                return false;
            } catch (LicenseNotFoundException e) {
                log.debug("License with name [" + licenseName + "] unique and can be created");
                return true;
            }
        } else {
            License licenseById = licensesService.getLicenseById(licenseId);
            try {
                License licenseByName = licensesService.getLicenseByName(licenseName);
                if (licenseById.getLicenseName().equals(licenseByName.getLicenseName())) {
                    log.debug("License with name [" + licenseName + "] duplicates current license name and can be modified");
                    return true;
                } else {
                    log.debug("License with name [" + licenseName + "] already exists");
                    return false;
                }
            } catch (LicenseNotFoundException e) {
                log.debug("License with name [" + licenseName + "] unique and can be created");
                return true;
            }
        }
    }
}
